package com.rest.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.scribe.model.Token;

import com.api.client.OAuthProvider;
import com.api.enums.ApiScheme;
import com.api.model.ApiConsumer;
import com.api.model.ApiEnvironment;
import com.api.model.ApiOAuth;
import com.api.model.ApiUser;
import com.rest.LoginRequest;
import com.rest.LoginService;
import com.rest.client.RestClientException;

public class LoginServiceImpl implements LoginService {

	private final Map<String, ApiEnvironment> environmentsMap;

	public LoginServiceImpl(List<ApiEnvironment> environments) {
		this.environmentsMap = new HashMap<String, ApiEnvironment>();
		for (ApiEnvironment environment : environments) {
			if (environmentsMap.containsKey(environment.getHost())) {
				throw new IllegalStateException(String.format("Cannot be two environments with same host: '%s'", environment.getHost()));
			} else {
				environmentsMap.put(environment.getHost(), environment);
			}
		}
	}

	@Override
	public ApiUser login(LoginRequest request) {

		try {

			ApiEnvironment env = request.getEnvironment();
			ApiOAuth oauth = env.getOauth();
			ApiConsumer consumer = env.getConsumer();

			Token consumerToken = new Token(consumer.getKey(), consumer.getSecret());

			String baseUrl = env.getScheme() + "://" + env.getHost();

			String requestEnpoint = baseUrl + oauth.getRequestEndpoint();
			String accessEndpoint = baseUrl + oauth.getAccessEndpoint();
			String authorizationEndpoint = baseUrl + oauth.getAuthorizationUrl();

			OAuthProvider provider = new OAuthProvider(requestEnpoint, accessEndpoint, authorizationEndpoint, consumerToken);

			Token access = provider.getAccessToken(request.getUsername(), request.getPassword());

			return new ApiUser(access.getToken(), access.getSecret());

		} catch (Exception e) {

			throw new RestClientException(e);
		}
	}

	@Override
	public ApiUser loginByForm(String username, String password, String scheme, String host) {
		try {
			if (!environmentsMap.containsKey(host)) {
				throw new IllegalStateException(String.format("The environment host '%s' doesn't exist", host));
			}
			ApiOAuth oauth = environmentsMap.get(host).getOauth();
			ApiConsumer consumer = environmentsMap.get(host).getConsumer();
			ApiEnvironment requestEnvironment = new ApiEnvironment();
			requestEnvironment.setScheme(ApiScheme.valueOf(scheme));
			requestEnvironment.setHost(host);
			requestEnvironment.setOauth(oauth);
			requestEnvironment.setConsumer(consumer);

			LoginRequest request = new LoginRequest();
			request.setUsername(username);
			request.setPassword(password);
			request.setEnvironment(requestEnvironment);

			return login(request);

		} catch (Exception e) {

			throw new RestClientException(e);
		}
	}
}
